import numpy as np
import httplib2
import os
import uuid
from PIL import Image,ImageEnhance,ImageFilter

base_dir = "D:/box/captcha1/"
def getPic(filename,url= 'http://www.zhongdengwang.org.cn/rs/include/vcodeimage.jsp'):
    h = httplib2.Http()
    resp, content = h.request(url)
    path = base_dir+"%s.png"% filename

    document = open(path, "wb+");
    document.write(content)
    document.close()

def getTest():
    for i in range(100):
        getPic("valid/%s"%str(uuid.uuid4()))
def splitPicture(path):
    im = Image.open(path)
    enhancer = ImageEnhance.Contrast(im)
    #去除干扰
    im = enhancer.enhance(5)
    # 去背景色
    imgry = im.convert('1')
    data = imgry.getdata()
    w,h = imgry.size


    # 切割图片
    imgCrop1 = imgry.crop((5,0,18,20))
    imgCrop2 = imgry.crop((19,0,30,20))
    imgCrop3 = imgry.crop((31,0,44,20))
    imgCrop4 = imgry.crop((45,0,56,20))

    return imgCrop1,imgCrop2,imgCrop3,imgCrop4

def splitAll():
    rootdir = "d:/box/captcha/src/"
    list = os.listdir(rootdir) #列出文件夹下所有的目录与文件
    for i in range(0,len(list)):
        path = os.path.join(rootdir,list[i])
        if os.path.isfile(path):
                   #你想对文件的操作
            c1,c2,c3,c4 = splitPicture(path)
            c1.save(base_dir+"category/unknown/%s.png"%uuid.uuid4())
            c2.save(base_dir+"category/unknown/%s.png"%uuid.uuid4())
            c3.save(base_dir+"category/unknown/%s.png"%uuid.uuid4())
            c4.save(base_dir+"category/unknown/%s.png"%uuid.uuid4())

def softmax(x):
    max_x = np.max(x)
    exp_x = np.exp(x-max_x)
    return exp_x/np.sum(exp_x)


def softmax_loss(x, y):
    probs = np.exp(x - np.max(x, axis=1, keepdims=True))
    probs /= np.sum(probs, axis=1, keepdims=True)
    N = x.shape[0]
    loss = -np.sum(np.log(probs[np.arange(N), y])) / N
    dx = probs.copy()
    dx[np.arange(N), y] -= 1
    dx /= N

    return loss, dx

def batchGradientDescent(x, y, theta, alpha, m, maxIterations):
    xTrains = x.transpose()
    for i in range(0, maxIterations):
        loss_a,hypothesis = softmax_loss(np.dot(x, theta),y)
        #hypothesis = np.dot(x,theta)
        if i%100 == 0:
            print(i,loss_a)
        #loss = hypothesis - y
        #print(loss)
        gradient = np.dot(xTrains, hypothesis)
        theta = theta - alpha * gradient
    return theta

def fmt_data(image):
    x_data = np.asarray(image,dtype=int)
    column_1 = np.ones([1,20])
    if(x_data.shape[1]==11):
        x_data = np.column_stack((x_data,column_1[0]))
        x_data = np.column_stack((x_data,column_1[0]))
    if(x_data.shape[1]==12):
        x_data = np.column_stack((x_data,column_1[0]))
    return x_data
def realValue(picture,theta):
    x_valid = fmt_data(picture)
    result = x_valid.reshape([20*13]).dot(theta)
    probs = np.exp(result - np.max(result,  keepdims=True))
    probs /= np.sum(probs,  keepdims=True)
    index = np.where(probs==np.max(probs))
    return index[0][0]

def outTo(theta):
    rootdir = base_dir+"test/"
    outdir = base_dir+"test_result/%s"
    files = os.listdir(rootdir)
    for i in files:
        c1,c2,c3,c4 = splitPicture(rootdir+i)
        fileName = "%d%d%d%d-%s.png"%(realValue(c1,theta),realValue(c2,theta),realValue(c3,theta),realValue(c4,theta),uuid.uuid4())
        im = Image.open(rootdir+i)
        im.save(outdir%fileName)
def getData():
    fileFmt = base_dir+"category/%s/%s"
    rootdir = base_dir+"category/"
    list = os.listdir(rootdir)
    x = []
    y = []
    for i in list:
        x_root = os.listdir(rootdir+str(i))
        for j in x_root:
            image = Image.open(fileFmt%(i,j))
            x_data = np.asarray(image,dtype=int)
            column_1 = np.ones([1,20])

            if(x_data.shape[1]==11):
                x_data = np.column_stack((x_data,column_1[0]))
                x_data = np.column_stack((x_data,column_1[0]))
            if(x_data.shape[1]==12):
                x_data = np.column_stack((x_data,column_1[0]))


            x.append(x_data.reshape([20*13]))

            y_data = np.zeros([10])
            y_data[int(i)] = 1
            y.append(y_data)
            #y.append(int(i))

    return x,y

def appendImg(c1,x,y,y_index):
    fill_x_11 = np.ones([11,13])
    fill_x_12 = np.ones([12,13])
    x_data = np.asarray(c1,dtype=int)

    if(x_data.shape[1]==11):
        x_data = np.matmul(x_data,fill_x_11)
    if(x_data.shape[1]==12):
        x_data = np.matmul(x_data,fill_x_12)


    x.append(x_data.reshape([20*13]))


    y_data = np.zeros([10])

    y_data[int(y_index)] = 1
    y.append(y_data)
def getTestData():
    rootdir = base_dir+"valid_result/"
    list = os.listdir(rootdir)
    x = []
    y = []
    for j in list:
        c1,c2,c3,c4 = splitPicture(rootdir+j)
        appendImg(c1,x,y,y_index = j.split('-')[0][0])
        appendImg(c2,x,y,y_index = j.split('-')[0][1])
        appendImg(c3,x,y,y_index = j.split('-')[0][2])
        appendImg(c4,x,y,y_index = j.split('-')[0][3])

    return np.asarray(x),np.asarray(y)

def train():

    x1,y1 = getData()


    x = np.array(x1)
    y = np.array(y1)

    w1 = np.zeros([260,10])
    b1 = np.zeros([1,10])


    alpha = 0.01
    m,n = x.shape
    w1 = batchGradientDescent(x,y,w1,alpha,m,10000)

    #c1,c2,c3,c4 = splitPicture("D:/box/captcha/valid/873c2ece-7090-4f5b-b604-45c4e4fae7e8.png")

    #print(realValue(c1,w1),realValue(c2,w1),realValue(c3,w1),realValue(c4,w1))
    outTo(w1)

#train()

#x = np.array(dtype=float)